package com.chenyaowei.product.service.impl;


import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import com.chenyaowei.common.constant.CacheConstants;
import com.chenyaowei.common.core.redis.RedisCache;
import com.chenyaowei.common.utils.SecurityUtils;
import com.chenyaowei.common.utils.StringUtils;
import com.chenyaowei.elasticsearch.mapper.ProductMapper;
import com.chenyaowei.elasticsearch.model.Product;
import com.chenyaowei.marketing.domain.CywSkuBounds;
import com.chenyaowei.marketing.domain.CywSpuDiscount;
import com.chenyaowei.marketing.domain.CywSpuFullReduction;
import com.chenyaowei.marketing.service.ICywSkuBoundsService;
import com.chenyaowei.marketing.service.ICywSpuDiscountService;
import com.chenyaowei.marketing.service.ICywSpuFullReductionService;
import com.chenyaowei.member.domain.CywMemberCollectSpu;
import com.chenyaowei.member.service.ICywMemberCollectSpuService;
import com.chenyaowei.product.bo.CommentLevelTotalBO;
import com.chenyaowei.product.domain.*;
import com.chenyaowei.product.request.ProductReleaseRequest;
import com.chenyaowei.product.request.ProductSearchRequest;
import com.chenyaowei.product.service.*;
import com.chenyaowei.product.vo.ProductInfoVO;
import com.chenyaowei.product.vo.ProductSearchConditionVO;
import com.chenyaowei.product.vo.ProductStatsInfoVO;
import com.chenyaowei.ware.bo.SkuStockCountBO;
import com.chenyaowei.ware.service.ICywWareSkuService;
import org.apache.commons.collections4.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.PostConstruct;
import java.util.*;
import java.util.stream.Collectors;

/**
 * The type Cyw product service.
 */
@Service
public class CywProductServiceImpl implements CywProductService {

    @Autowired
    private RedisCache redisCache;

    @Autowired
    private ICywProSpuInfoService spuInfoService;

    @Autowired
    private ICywSpuDiscountService spuDiscountService;

    @Autowired
    private ICywSpuFullReductionService spuFullReductionService;

    @Autowired
    private ICywProSpuImagesService spuImagesService;

    @Autowired
    private ICywProductAttrValueService baseAttrValueService;

    @Autowired
    private ICywProSkuInfoService skuInfoService;

    @Autowired
    private ICywProductAttrService productAttrService;

    @Autowired
    private ICywProSkuImagesService skuImagesService;

    @Autowired
    private ICywProSkuSaleAttrValueService saleAttrValueService;

    @Autowired
    private ICywSkuBoundsService boundsService;

    @Autowired
    private ICywProductCategoryService categoryService;

    @Autowired
    private ICywBrandCategoryRelationService brandCategoryRelationService;

    @Autowired
    private ICywProductAttrValueService productAttrValueService;

    @Autowired
    private ICywProductBrandService brandService;

    @Autowired
    private ICywWareSkuService wareSkuService;

    @Autowired
    private ICywProSpuCommentService commentService;

    @Autowired
    private ICywProSpuCommentReplyService commentReplyService;

    @Autowired
    private ICywMemberCollectSpuService memberCollectSpuService;

    @Autowired
    private ProductMapper esProductMapper;

    private static final Logger log = LoggerFactory.getLogger(CywProductServiceImpl.class);


    //    @PostConstruct
    private void init() {
        if (!esProductMapper.existsIndex("product")) {
            log.info("商品数据初始化开始...");
            List<ProductInfoVO> list = selectProductInfoList();
            log.info("创建ES索引...");
            esProductMapper.createIndex();
            log.info("ES索引创建完毕");
            List<Product> esProductList = buildEsProductList(list);
            log.info("ES数据初始化开始...");
            esProductMapper.insertBatch(esProductList);
            log.info("商品数据初始化结束");
        }
    }

    @Override
    public List<Product> buildEsProductList(List<ProductInfoVO> list) {
        List<Product> esProductList = new ArrayList<>();
        list.forEach(spuInfo -> {
            spuInfo.getSkuInfos().forEach(skuInfo -> {
                Product product = new Product();
                product.setSkuId(skuInfo.getSkuId());
                product.setSpuId(skuInfo.getSpuId());
                product.setSpuName(spuInfo.getSpuName());
                product.setSkuName(skuInfo.getSkuName());
                product.setSkuDesc(skuInfo.getSkuDesc());
                product.setBrandName(spuInfo.getBrandName());
                product.setCatalogName(spuInfo.getCatName());
                product.setSkuDefaultImg(skuInfo.getSkuDefaultImg());
                product.setSkuTitle(skuInfo.getSkuTitle());
                product.setSkuSubTitle(skuInfo.getSkuSubTitle());
                product.setPrice(skuInfo.getPrice());
                product.setSaleCount(Long.valueOf(skuInfo.getSaleCount()));
                esProductList.add(product);
            });
        });
        return esProductList;
    }

    /**
     * 商品详情
     */
    @Override
    public ProductInfoVO productInfo(Long spuId, String token) {
        ProductInfoVO productInfoVO = selectProductInfoList().stream().filter(item -> item.getSpuId().equals(spuId)).collect(Collectors.toList()).get(0);
        List<CywProSkuInfo> skuInfos = productInfoVO.getSkuInfos();
        List<Long> skuIds = skuInfos.stream().map(CywProSkuInfo::getSkuId).collect(Collectors.toList());
        // 库存
        List<SkuStockCountBO> skuStockCountBOS = wareSkuService.countStockBySkuIds(skuIds);
        skuInfos.forEach(skuInfo -> {
            SkuStockCountBO skuStockCountBO = skuStockCountBOS.stream().filter(item -> skuInfo.getSkuId().equals(item.getSkuId())).findFirst().get();
            skuInfo.setTotalStock(skuStockCountBO.getTotalStock());
            // 图集排序，值越小越靠前
            skuInfo.setSkuImages(skuInfo.getSkuImages().stream().sorted(Comparator.comparing(CywProSkuImages::getImgSort)).collect(Collectors.toList()));
        });
        productInfoVO.setSpuImageList(productInfoVO.getSpuImageList().stream().sorted(Comparator.comparing(CywProSpuImages::getImageSord)).collect(Collectors.toList()));
        Boolean collected = false;
        if (StringUtils.isNotEmpty(token)) {
            CywMemberCollectSpu memberCollectSpu = memberCollectSpuService.selectInfoByMemberIdAndSpuId(SecurityUtils.getUserId(), spuId);
            collected = ObjectUtil.isNotEmpty(memberCollectSpu);
        }
        CommentLevelTotalBO commentLevelTotalBO = commentService.countCommentLevelTotal(spuId);
        productInfoVO.setCollected(collected);
        productInfoVO.setCommentCount(commentLevelTotalBO.getTotal());
        return productInfoVO;
    }


    /**
     * 商品检索
     **/
    @Override
    public List<CywProSkuInfo> productSearch(ProductSearchRequest productSearchRequest) {
        // TODO es 搜索引擎
        List<CywProSkuInfo> list = new ArrayList<>();
        // 所属分类，前端请求必须携带的
        Long catId = productSearchRequest.getCatId();
        // 商品数据集
        List<ProductInfoVO> productInfoVOList = selectProductInfoList().stream().filter(item -> item.getOriginCatIds().contains(catId)).collect(Collectors.toList());
        // 按照品牌筛选
        Long brandId = productSearchRequest.getBrandId();
        if (brandId != null) {
            productInfoVOList = productInfoVOList.stream().filter(item -> item.getBrandId().equals(brandId)).collect(Collectors.toList());
        }
        // 按照规格属性筛选
        List<CywProductAttrValue> attrs = productSearchRequest.getAttrs();
        if (CollectionUtil.isNotEmpty(attrs)) {
            // init 标志位
            // lamdba 不能修改 外部变量的值，需要用 AtomicReference<Boolean> flag 或者改成 for循环。
/*            AtomicReference<Boolean> flag = new AtomicReference<>(false);
            productInfoVOList.forEach(item -> {
                Map<Long, String> baseAttrMap = item.getBaseAttrs().stream().collect(Collectors.toMap(CywProductAttrValue::getAttrId, CywProductAttrValue::getAttrValue));
                item.getSkuInfos().forEach(skuInfo -> {
                    attrs.forEach(attr -> {
                        if (!attr.getAttrValue().equals(baseAttrMap.get(attr.getAttrId()))) {
                            // 目标规格 与 商品规格 不匹配，直接return 下面的循环不必再继续
                            flag.set(true);
                            return;
                        }
                    });
                    if (flag.get()) {
                        // 不匹配，直接结束该 spu 的循环
                        // 重置标志位
                        flag.set(false);
                        return;
                    }

                    list.add(skuInfo);
                });
            });*/
            Boolean flag = false;
            for (ProductInfoVO productInfoVO : productInfoVOList) {
                Map<Long, String> baseAttrMap = productInfoVO.getBaseAttrs().stream().collect(Collectors.toMap(CywProductAttrValue::getAttrId, CywProductAttrValue::getAttrValue));
                List<CywProSkuInfo> skuInfos = productInfoVO.getSkuInfos();
                for (CywProSkuInfo skuInfo : skuInfos) {
                    for (CywProductAttrValue attr : attrs) {
                        if (!attr.getAttrValue().equals(baseAttrMap.get(attr.getAttrId()))) {
                            // 目标规格 与 商品规格 不匹配，直接return 下面的循环不必再继续
                            flag = true;
                            break;
                        }
                    }
                    if (flag) {
                        // 不匹配，直接结束该 spu 的循环
                        // 重置标志位
                        flag = false;
                        break;
                    }

                    list.add(skuInfo);
                }
            }
            return list;
        }
        productInfoVOList.forEach(item -> item.getSkuInfos().forEach(skuInfo -> list.add(skuInfo)));
        return list;
    }

    /**
     * 商品信息
     **/
    private List<ProductInfoVO> selectProductInfoList() {
        // TODO es 搜索引擎
        List<ProductInfoVO> cacheObject = redisCache.getCacheObject(CacheConstants.PRODUCT_CACHE + "info");
        if (CollectionUtils.isNotEmpty(cacheObject)) {
            return cacheObject;
        } else {
            // TODO 并发加锁，查数据库前再查一次缓存
            // TODO 异步编排
            // 1、找到所有未下架的spu
            CywProSpuInfo cywProSpuInfo = new CywProSpuInfo();
            cywProSpuInfo.setPublishStatus(1);
            List<CywProSpuInfo> spuInfoList = spuInfoService.selectCywProSpuInfoList(cywProSpuInfo);
            if (CollectionUtil.isEmpty(spuInfoList)) {
                return null;
            }
            List<ProductInfoVO> list = buildProductInfoVOList(spuInfoList);
            redisCache.setCacheObject(CacheConstants.PRODUCT_CACHE + "info", list);
            System.out.println(list);
            return list;
        }
    }

    @Override
    public List<ProductInfoVO> buildProductInfoVOList(List<CywProSpuInfo> spuInfoList) {
        List<ProductInfoVO> list = new ArrayList<>();
        List<Long> spuIds = spuInfoList.stream().map(CywProSpuInfo::getSpuId).collect(Collectors.toList());
        // 所有spu介绍图集
        List<CywProSpuImages> spuImageList = spuImagesService.selectListBySpuIds(spuIds);
        // 所有品牌
        List<Long> brandIds = spuInfoList.stream().map(CywProSpuInfo::getBrandId).collect(Collectors.toList());
        List<CywProductBrand> brandList = brandService.selectListByBrandIds(brandIds);
        // 所有base属性
        List<CywProductAttrValue> baseAttrValueList = baseAttrValueService.selectListBySpuIds(spuIds);
        // 所有spu折扣信息
        List<CywSpuFullReduction> spuFullReductionList = spuFullReductionService.selectListBySpuIds(spuIds);
        // 所有spu满减信息
        List<CywSpuDiscount> spuDiscountList = spuDiscountService.selectListBySpuIds(spuIds);
        // 所有sku基本信息
        List<CywProSkuInfo> skuInfoList = skuInfoService.selectListBySpuIds(spuIds);
        List<Long> skuIds = skuInfoList.stream().map(CywProSkuInfo::getSkuId).collect(Collectors.toList());
        // 所以sku图集
        List<CywProSkuImages> skuImagesList = skuImagesService.selectListBySkuIds(skuIds);
        // 所有sku销售属性
        List<CywProSkuSaleAttrValue> saleAttrValueList = saleAttrValueService.selectListBySkuIds(skuIds);
        // 所有base属性
        List<CywSkuBounds> boundsList = boundsService.selectListBySkuIds(skuIds);
        //找到所有的显示的分类
        CywProductCategory category = new CywProductCategory();
        category.setShowStatus(0);
        List<CywProductCategory> categoryList = categoryService.selectCywProductCategoryList(category);
        skuInfoList.forEach(skuInfo -> {
            Long skuId = skuInfo.getSkuId();
            // 设置sku的图集
            skuInfo.setSkuImages(skuImagesList.stream().filter(skuImage -> skuImage.getSkuId().equals(skuId)).collect(Collectors.toList()));
            // 设置销售属性
            skuInfo.setAttrs(saleAttrValueList.stream().filter(saleAttrValue -> saleAttrValue.getSkuId().equals(skuId)).collect(Collectors.toList()));
            // 设置积分信息
            skuInfo.setSkuBounds(boundsList.stream().filter(bounds -> bounds.getSkuId().equals(skuId)).findFirst().orElse(null));
        });
        spuInfoList.forEach(spu -> {
            Long spuId = spu.getSpuId();
            ProductInfoVO productInfoVO = new ProductInfoVO();
            // 设置spu基本信息
            BeanUtils.copyProperties(spu, productInfoVO);
            // 设置品牌名称
            productInfoVO.setBrandName(brandList.stream().filter(brand -> brand.getBrandId().equals(spu.getBrandId())).findFirst().get().getName());
            // 设置spu介绍图集
            List<CywProSpuImages> spuImageTempList = new ArrayList<>();
            spuImageList.stream().filter(spuImage -> spuImage.getSpuId().equals(spuId)).forEach(spuImageTempList::add);
            productInfoVO.setSpuImageList(spuImageTempList);
            // 设置base属性
            List<CywProductAttrValue> baseAttrInfoListTemp = new ArrayList<>();
            baseAttrValueList.stream().filter(baseAttrValue -> baseAttrValue.getSpuId().equals(spuId)).forEach(baseAttrInfoListTemp::add);
            productInfoVO.setBaseAttrs(baseAttrInfoListTemp);
            // 设置祖宗分类Ids（含自身）
            CywProductCategory source = categoryList.stream().filter(item -> item.getCatId().equals(spu.getCatalogId())).findFirst().orElse(null);
            List<Long> originCatIds = findOriginCatIds(source, categoryList, new ArrayList<>());
            productInfoVO.setOriginCatIds(originCatIds);
            // 设置满减
            CywSpuFullReduction spuFullReduction = spuFullReductionList.stream().filter(item -> item.getSpuId().equals(spuId)).findFirst().orElse(null);
            productInfoVO.setSpuFullReduction(spuFullReduction);
            // 设置折扣
            CywSpuDiscount spuDiscount = spuDiscountList.stream().filter(item -> item.getSpuId().equals(spuId)).findFirst().orElse(null);
            productInfoVO.setSpuDiscount(spuDiscount);
            // 设置sku信息
            List<CywProSkuInfo> skuInfoListTemp = skuInfoList.stream().filter(skuInfo -> skuInfo.getSpuId().equals(spuId)).collect(Collectors.toList());
            productInfoVO.setSkuInfos(skuInfoListTemp);
            // 设置销售属性条件
            Map<String, String> saleAttrConditionMap = new HashMap<>();
            productInfoVO.getSkuInfos().forEach(item -> {
                List<CywProSkuSaleAttrValue> attrs = item.getAttrs();
                attrs.forEach(attr -> {
                    String key = attr.getAttrId() + "," + attr.getAttrName();
                    String attrValue = attr.getAttrValue();
                    String attrValues = saleAttrConditionMap.get(key);
                    if (!StringUtils.isEmpty(attrValues) && !attrValues.contains(attrValue)) {
                        saleAttrConditionMap.put(key, attrValues + "," + attrValue);
                    } else {
                        saleAttrConditionMap.put(key, attrValue);
                    }
                });
            });
            List<ProductInfoVO.ProductSaleAttrCondition> saleAttrConditionTempList = new ArrayList<>();
            saleAttrConditionMap.forEach((key, value) -> {
                ProductInfoVO.ProductSaleAttrCondition productSaleAttrCondition = new ProductInfoVO.ProductSaleAttrCondition();
                productSaleAttrCondition.setAttrId(Long.valueOf(key.split(String.valueOf(","))[0]));
                productSaleAttrCondition.setAttrName(key.split(String.valueOf(","))[1]);
                productSaleAttrCondition.setAttrValues(value);
                saleAttrConditionTempList.add(productSaleAttrCondition);
            });
            productInfoVO.setSaleAttrConditions(saleAttrConditionTempList);
            list.add(productInfoVO);
        });
        return list;
    }

    @Override
    public ProductStatsInfoVO productStatsInfo(Long skuId) {
        ProductStatsInfoVO productStatsInfoVO = new ProductStatsInfoVO();
        SkuStockCountBO skuStockCountBO = wareSkuService.countStockBySkuIds(Arrays.asList(skuId)).stream().findFirst().get();
        productStatsInfoVO.setStocked(skuStockCountBO.getTotalStock());
        CywProSkuInfo skuInfo = skuInfoService.selectCywProSkuInfoBySkuId(skuId);
        productStatsInfoVO.setSaleCount(skuInfo.getSaleCount());
        return productStatsInfoVO;
    }

    @Override
    public int collectSpu(Long spuId) {
        CywMemberCollectSpu memberCollectSpu = new CywMemberCollectSpu();
        memberCollectSpu.setSpuId(spuId);
        memberCollectSpu.setMemberId(SecurityUtils.getUserId());
        CywProSpuInfo spuInfo = spuInfoService.selectCywProSpuInfoBySpuId(spuId);
        memberCollectSpu.setSpuName(spuInfo.getSpuName());
        CywProSkuInfo skuInfo = skuInfoService.selectListBySpuIds(Arrays.asList(spuId)).stream().findFirst().get();
        memberCollectSpu.setCoverImg(skuInfo.getSkuDefaultImg());
        memberCollectSpu.setCreateTime(new Date());
        return memberCollectSpuService.insertCywMemberCollectSpu(memberCollectSpu);
    }

    @Override
    public List<CywProSkuInfo> productRecommend() {
        List<CywProSkuInfo> list = new ArrayList<>();
        // TODO 推荐算法、协同过滤推荐
        List<ProductInfoVO> productInfoVOList = selectProductInfoList();
        productInfoVOList.forEach(item -> item.getSkuInfos().forEach(skuInfo -> list.add(skuInfo)));
        if (list.size() > 40) {
            return list.stream().sorted(Comparator.comparing(CywProSkuInfo::getSkuId)).limit(40).collect(Collectors.toList());
        }
        return list;
    }

    /**
     * 商品发布
     **/
    @Transactional(rollbackFor = {Exception.class})
    @Override
    public int productRelease(ProductReleaseRequest productReleaseRequest) {
        // TODO 异步编排
        /**
         *     private CywProSpuInfo spuInfo;
         *     private CywSpuDiscount spuDiscount;
         *     private CywSpuFullReduction spuFullReduction;
         *     private String proSpuImages;
         *     private List<CywProductAttrValue> baseAttrs;
         *     private List<CywProSkuInfo> skuList;
         */
        // 1、保存spu基本信息，拿到spuId
        CywProSpuInfo spuInfo = productReleaseRequest.getSpuInfo();
        spuInfoService.insertCywProSpuInfo(spuInfo);
        Long spuId = spuInfo.getSpuId();
        Long catalogId = spuInfo.getCatalogId();
        Long brandId = spuInfo.getBrandId();

        // 保存spu折扣信息
        CywSpuDiscount spuDiscount = productReleaseRequest.getSpuDiscount();
        spuDiscount.setSpuId(spuId);
        spuDiscountService.insertCywSpuDiscount(spuDiscount);

        // 保存spu满减信息
        CywSpuFullReduction spuFullReduction = productReleaseRequest.getSpuFullReduction();
        spuFullReduction.setSpuId(spuId);
        spuFullReductionService.insertCywSpuFullReduction(spuFullReduction);

        // 保存spu介绍信息
        List<CywProSpuImages> spuImagesList = new ArrayList<>();
        String proSpuImages = productReleaseRequest.getProSpuImages();
        List<String> spuImages = Arrays.asList(proSpuImages.split(","));
/*        spuImages.forEach(url -> {
            CywProSpuImages entity = new CywProSpuImages();
            entity.setSpuId(spuId);
            entity.setImageUrl(url);
            spuImagesList.add(entity);
        });*/
        for (int i = 0; i < spuImages.size(); i++) {
            CywProSpuImages entity = new CywProSpuImages();
            entity.setSpuId(spuId);
            entity.setImageUrl(spuImages.get(i));
            entity.setImageSord(i);
            spuImagesList.add(entity);
        }
        spuImagesService.saveBatch(spuImagesList);

        // 保存spu基本属性
        List<CywProductAttrValue> baseAttrs = productReleaseRequest.getBaseAttrs();
        // 基本属性是否快速展示
        List<Long> attrIds = baseAttrs.stream().map(CywProductAttrValue::getAttrId).collect(Collectors.toList());
        Map<Long, Long> quickShowMap = productAttrService.selectCywProductAttrListByAttrIds(attrIds).stream().collect(Collectors.toMap(CywProductAttr::getAttrId, CywProductAttr::getShowDesc));
        baseAttrs.forEach(item -> {
            item.setSpuId(spuId);
            item.setQuickShow(quickShowMap.get(item.getAttrId()));
        });
        baseAttrValueService.saveBatch(baseAttrs);

        // 保存sku信息
        List<CywProSkuInfo> skuList = productReleaseRequest.getSkuList();
        List<CywProSkuImages> skuImagesList = new ArrayList<>();
        List<CywProSkuSaleAttrValue> saleAttrs = new ArrayList<>();
        List<CywSkuBounds> boundsList = new ArrayList<>();
        skuList.forEach(item -> {
            item.setSpuId(spuId);
            item.setCatalogId(catalogId);
            item.setBrandId(brandId);
            // 从sku图片集中筛选sku默认图片
            List<CywProSkuImages> skuImages = item.getSkuImages();
            CywProSkuImages defaultImgEntity = skuImages.stream().filter(entity -> entity.getDefaultImg() == 1).findFirst().orElse(null);
            item.setSkuDefaultImg(defaultImgEntity.getImgUrl());
            skuInfoService.insertCywProSkuInfo(item);
            Long skuId = item.getSkuId();
            // sku图片集
/*            skuImages.forEach(entity -> {
                entity.setSkuId(skuId);
                skuImagesList.add(entity);
            });*/
            for (int i = 0; i < skuImages.size(); i++) {
                CywProSkuImages entity = skuImages.get(i);
                entity.setSkuId(skuId);
                entity.setImgSort(i);
                skuImagesList.add(entity);
            }
            // sku销售属性
            List<CywProSkuSaleAttrValue> attrs = item.getAttrs();
            attrs.forEach(attr -> {
                attr.setSkuId(skuId);
                saleAttrs.add(attr);
            });
            // sku积分信息
            CywSkuBounds skuBounds = item.getSkuBounds();
            skuBounds.setSkuId(skuId);
            boundsList.add(skuBounds);

        });

        // 保存sku图片集
        skuImagesService.saveBatch(skuImagesList);

        // 保存sku销售属性
        saleAttrValueService.saveBatch(saleAttrs);

        // 保存sku积分信息
        return boundsService.savaBatch(boundsList);
    }


    /**
     * 商品筛选条件
     **/
    @Override
    public ProductSearchConditionVO productSearchCondition() {
        // TODO
        ProductSearchConditionVO cacheObject = redisCache.getCacheObject(CacheConstants.PRODUCT_CACHE + "search_condition");
        if (ObjectUtil.isNotEmpty(cacheObject)) {
            return cacheObject;
        } else {
            // TODO 并发加锁，查数据库前再查一次缓存
            ProductSearchConditionVO productSearchConditionVO = new ProductSearchConditionVO();
            List<ProductSearchConditionVO.ProductCategory> categories = new ArrayList<>();
            // 所有显示的分类
            CywProductCategory category = new CywProductCategory();
            category.setShowStatus(0);
            List<CywProductCategory> allCategories = categoryService.selectCywProductCategoryList(category);
            allCategories.forEach(item -> {
                ProductSearchConditionVO.ProductCategory productCategory = new ProductSearchConditionVO.ProductCategory();
                BeanUtils.copyProperties(item, productCategory);
                categories.add(productCategory);
            });

            // 所有分类id
            List<Long> catIds = categories.stream().map(ProductSearchConditionVO.ProductCategory::getCatId).collect(Collectors.toList());
            // 所有分类品牌管理关系
            List<CywBrandCategoryRelation> allBrandCategoryRelations = brandCategoryRelationService.selectListByCatelogIds(catIds);
            // 所有可检索的未禁用的基础属性
            CywProductAttr cywProductAttr = new CywProductAttr();
            cywProductAttr.setSearchType(1);
            cywProductAttr.setEnable(0);
            cywProductAttr.setAttrType(1);
            List<CywProductAttr> allProductAttrs = productAttrService.selectCywProductAttrList(cywProductAttr);
            List<Long> attrIds = allProductAttrs.stream().map(CywProductAttr::getAttrId).collect(Collectors.toList());
            List<CywProductAttrValue> allBaseAttrs = productAttrValueService.selectListByAttrIds(attrIds);

            //所有未下架的spu信息
            CywProSpuInfo cywProSpuInfo = new CywProSpuInfo();
            cywProSpuInfo.setPublishStatus(1);
            List<CywProSpuInfo> allSpuInfos = spuInfoService.selectCywProSpuInfoList(cywProSpuInfo);

            // 品牌、属性
            categories.forEach(item -> {
                // 品牌绑定的是子分类id，传的是父分类id时需要递归找到所有儿子的id
                List<Long> descendantCatIds = new ArrayList<>();
                if (item.getCatLevel() != 3L) {
                    findDescendantCatIds(item.getCatId(), allCategories, descendantCatIds);
                } else {
                    descendantCatIds.add(item.getCatId());
                }
                List<CywBrandCategoryRelation> brands = allBrandCategoryRelations.stream().filter(relation -> descendantCatIds.contains(relation.getCatelogId())).collect(Collectors.toList());
                Set<ProductSearchConditionVO.ProductBrand> productBrands = new HashSet<>();
                brands.forEach(brand -> {
                    ProductSearchConditionVO.ProductBrand productBrand = new ProductSearchConditionVO.ProductBrand();
                    BeanUtils.copyProperties(brand, productBrand);
                    productBrands.add(productBrand);
                });
                item.setBrands(productBrands);
                //属性
                List<ProductSearchConditionVO.ProductAttr> productAttrs = new ArrayList<>();
                // cyw_product_attr表 属性绑定的是顶级分类id ，这样写的话所有子类的属性都和父类的一样了
/*                Long topCatelogById = findTopCatelogById(item.getCatId(), allCategories);
                List<CywProductAttr> attrs = allProductAttrs.stream().filter(attr -> attr.getCatelogId().equals(topCatelogById)).collect(Collectors.toList());
                attrs.forEach(attr -> {
                    ProductSearchConditionVO.ProductAttr productAttr = new ProductSearchConditionVO.ProductAttr();
                    BeanUtils.copyProperties(attr, productAttr);
                    productAttrs.add(productAttr);
                });*/
                // 通过cyw_product_attr_value表
                // 找到该分类（大类含子类）下的所有spu
                List<Long> spuIds = allSpuInfos.stream().filter(spuInfo -> descendantCatIds.contains(spuInfo.getCatalogId())).map(CywProSpuInfo::getSpuId).collect(Collectors.toList());
                List<CywProductAttrValue> attrValueList = allBaseAttrs.stream().filter(attr -> spuIds.contains(attr.getSpuId())).collect(Collectors.toList());

                // 按照attrId进行分组，将每一项的attrValue 去重 并用逗号分割拼接起来。
                Map<Long, String> attrMap = new HashMap<>();
                attrValueList.forEach(entity -> {
                    Long attrId = entity.getAttrId();
                    String attrValue = entity.getAttrValue();
                    String attrValues = attrMap.get(attrId);
                    if (!StringUtils.isEmpty(attrValues) && !attrValues.contains(attrValue)) {
                        attrMap.put(attrId, attrValues + "," + attrValue);
                    } else {
                        attrMap.put(attrId, attrValue);
                    }
                });

                // 去重，大类可能包含多个spu，spu会存在相同 attrId 的属性记录。
                List<CywProductAttrValue> attrValueSingleList = removeDuplicatesProductBaseAttr(attrValueList);
                attrValueSingleList.forEach(attr -> {
                    ProductSearchConditionVO.ProductAttr productAttr = new ProductSearchConditionVO.ProductAttr();
                    BeanUtils.copyProperties(attr, productAttr);
                    productAttr.setValueSelect(attrMap.get(attr.getAttrId()));
                    productAttrs.add(productAttr);
                });
                item.setAttrs(productAttrs);
            });

            //组装树形菜单
            List<ProductSearchConditionVO.ProductCategory> treeTableCategories = categories.stream().filter(item -> item.getCatLevel() == 1).collect(Collectors.toList());
            for (ProductSearchConditionVO.ProductCategory level1category : treeTableCategories) {
                List<ProductSearchConditionVO.ProductCategory> level2categories = categories.stream().filter(item -> item.getParentCid().equals(level1category.getCatId())).collect(Collectors.toList());
                for (ProductSearchConditionVO.ProductCategory level2category : level2categories) {
                    List<ProductSearchConditionVO.ProductCategory> level3category = categories.stream().filter(item -> item.getParentCid().equals(level2category.getCatId())).collect(Collectors.toList());
                    level2category.setChildren(level3category);
                }
                level1category.setChildren(level2categories);
            }

            productSearchConditionVO.setCategories(treeTableCategories);
            redisCache.setCacheObject(CacheConstants.PRODUCT_CACHE + "search_condition", productSearchConditionVO);
            return productSearchConditionVO;
        }
    }

    /**
     * 去除 attrId 重复的记录
     **/
    private List<CywProductAttrValue> removeDuplicatesProductBaseAttr(List<CywProductAttrValue> attrValueList) {
        List<CywProductAttrValue> result = new ArrayList<>();
        Set<Long> set = new HashSet<>();
        attrValueList.forEach(item -> set.add(item.getAttrId()));
        set.forEach(attrId -> {
            CywProductAttrValue cywProductAttrValue = attrValueList.stream().filter(item -> item.getAttrId().equals(attrId)).findFirst().orElse(null);
            result.add(cywProductAttrValue);
        });
        return result;
    }

    /**
     * 找到顶级子分类id
     **/
    private Long findTopCatelogById(Long catelogId, List<CywProductCategory> list) {
        CywProductCategory category = list.stream().filter(item -> catelogId.equals(item.getCatId())).findFirst().get();
        //顶级分类 level = 1L
        while (category.getCatLevel() != 1L) {
            Long parentCid = category.getParentCid();
            category = list.stream().filter(item -> parentCid.equals(item.getCatId())).findFirst().get();
        }
        return category.getCatId();
    }

    /**
     * 递归找到祖宗分类id
     **/
    private List<Long> findOriginCatIds(CywProductCategory source, List<CywProductCategory> list, List<Long> originCatIds) {
        originCatIds.add(source.getCatId());
        CywProductCategory parent = list.stream().filter(item -> item.getCatId().equals(source.getParentCid())).findFirst().orElse(null);
        if (ObjectUtil.isNotEmpty(parent)) {
            findOriginCatIds(parent, list, originCatIds);
        }
        return originCatIds;
    }

    /**
     * 递归找到所有子分类id
     **/
    private void findDescendantCatIds(Long catelogId, List<CywProductCategory> list, List<Long> descendantIds) {
        descendantIds.add(catelogId);
        List<CywProductCategory> children = list.stream().filter(item -> item.getParentCid().equals(catelogId)).collect(Collectors.toList());
        if (CollectionUtils.isNotEmpty(children)) {
            children.forEach(item -> {
                findDescendantCatIds(item.getCatId(), list, descendantIds);
            });
        }
    }

}

